/*
 *  Netzpult - Your desk on the web
 *  Copyright (C) 2011  Ulrich Hilger, http://uhilger.de
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/
 */

package de.uhilger.netzpult.client;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

import de.uhilger.netzpult.shared.Document;
import de.uhilger.netzpult.shared.Folder;


/**
 * Bedienoberfläche der Webanwendung Netzpult zum Verwalten von Dokumenten und
 * Ordnern
 * 
 * @author Copyright (c) Ulrich Hilger, http://uhilger.de
 * @author Published under the terms and conditions of the <a
 *         href="http://www.gnu.org/licenses/" target="_blank">GNU General
 *         Public License</a>
 */
public class Ablage extends AbstrakteGestalt {

	private static final int UNSELECTED = -1;
	private static final int DOC_ID_COL = 0;
	private static final int DOC_VERSION_COL = 1;
	private static final int DOC_ORDER_COL = 2;
	private static final int DOC_TIME_COL = 3;
	private static final int DOC_TITLE_COL = 4;

	private OwnerServiceAsync service;

	private BoundTree tree;
	private Grid grid;
	private int selectedRow = UNSELECTED;

	public Ablage(OwnerServiceAsync service) {
		super();
		this.service = service;
		
		grid = new Grid(1, 5);
		CellFormatter cellFormatter = grid.getCellFormatter();
		cellFormatter.setWidth(0, 0, "5%");
		cellFormatter.setWidth(0, 1, "5%");
		cellFormatter.setWidth(0, 2, "5%");
		cellFormatter.setWidth(0, 3, "20%");
		cellFormatter.setWidth(0, 4, "65%");
		grid.setStyleName("ablageGrid");
		grid.setCellPadding(5);
		grid.setCellSpacing(0);

		grid.addClickHandler(new GridClickHandler());
		grid.addDoubleClickHandler(new GridDoubleClickHandler());
		grid.setSize("100%", "100%");

		ScrollPanel docPanel = new ScrollPanel();
		docPanel.setWidget(grid);

		tree = new BoundTree(null, false, true);
		tree.setService(service);

		new GetRootFoldersCall(service, new AddFoldersCommand(), new LoginExitCommand()).execute();

		tree.addSelectionHandler(new AblageTreeSelectionHandler());

		ScrollPanel treePanel = new ScrollPanel();
		treePanel.setWidget(tree);
		tree.setSize("100%", "100%");

		SplitLayoutPanel ablage = new SplitLayoutPanel();
		ablage.addWest(treePanel, 200.0);
		ablage.add(docPanel);

		DockLayoutPanel layoutPanel = new DockLayoutPanel(Unit.EM);
		layoutPanel.addNorth(getMenu(), 2.0);
		layoutPanel.add(ablage);

		initWidget(layoutPanel);
	}

	private class GridDoubleClickHandler implements DoubleClickHandler {
		public void onDoubleClick(DoubleClickEvent event) {
			editDocument();
		}
	}

	private class GridClickHandler implements ClickHandler {
		public void onClick(ClickEvent event) {
			selectGridRow(grid.getCellForEvent(event).getRowIndex());
		}
	}
	
	private class AblageTreeSelectionHandler implements SelectionHandler<TreeItem> {
		public void onSelection(SelectionEvent<TreeItem> event) {
			Object selectedItem = event.getSelectedItem();
			if (selectedItem instanceof TreeItem) {
				updateDocumentList(null);
			}
		}
	}

	public void setOwnerService(OwnerServiceAsync service) {
		this.service = service;
	}

	private void updateDocumentList(Integer selectRow) {
		Folder folder = (Folder) tree.getSelectedItem().getUserObject();
		switch (folder.getId()) {
		case Folder.NOT_FILED_FOLDER_ID:
			new GetUnfiledDocumentsCall(service, new PopulateGridCommand(selectRow), new LoginExitCommand()).execute();
			break;
		case Folder.DRAFT_FOLDER_ID:
			new GetDraftDocumentsCall(service, new PopulateGridCommand(selectRow), new LoginExitCommand()).execute();
			break;
		case Folder.SHARED_FOLDER_ID:
			new GetSharedDocumentsCall(service, new PopulateGridCommand(selectRow), new LoginExitCommand()).execute();
			break;
		default:
			new GetDocumentsCall(service, new PopulateGridCommand(selectRow), new LoginExitCommand(), folder).execute();
			break;
		}
	}

	private void populateGrid(Grid grid, List<Document> docs, Integer selectRow) {
		unselectAll();
		grid.resizeRows(docs.size() + 1);
		Iterator<Document> i = docs.iterator();

		grid.setHTML(0, 0, "ID");
		grid.setHTML(0, 1, "Version");
		grid.setHTML(0, 2, "Reihenfolge");
		grid.setHTML(0, 3, "Zeit");
		grid.setHTML(0, 4, "Titel");

		int row = 1;
		while (i.hasNext()) {
			Document doc = i.next();
			grid.setHTML(row, 0, Integer.toString(doc.getId()));
			grid.setHTML(row, 1, Integer.toString(doc.getVersion()));
			grid.setHTML(row, 2, Integer.toString(doc.getOrder()));
			grid.setHTML(row, 3, getDateStr(doc.getCreationDateTime()));
			grid.setHTML(row, 4, doc.getTitle());
			++row;
		}
		if(selectRow != null && selectRow > 0) {
			selectGridRow(selectRow.intValue());
		} else {
			selectedRow = UNSELECTED;
		}
		grid.getRowFormatter().addStyleName(0, "headerRow");

	}
	
	private void selectGridRow(int row) {
		if (selectedRow > -1 && selectedRow < grid.getRowCount()) {
			grid.getRowFormatter().setStyleName(selectedRow, "unselectedDocGridRow");
		}
		//int row = grid.getCellForEvent(event).getRowIndex();
		if (row > 0) {
			selectedRow = row;
			grid.getRowFormatter().setStyleName(selectedRow, "selectedDocGridRow");
		}
	}

	private String getDateStr(Date date) {
		DateTimeFormat dateFormat = DateTimeFormat.getFormat("dd.MM.yyyy HH:mm:ss");
		return dateFormat.format(date);
	}

	private void editDocument() {
		if (selectedRow > -1) {
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			String appPath = getAppPath();
			if(appPath != null && appPath.length() > 0 && !appPath.equals("ablage") ) {
				Window.open(getBaseUrl() + "/" + appPath + "/texter/" + idStr, "_blank", null);
			} else {
				Window.open(getBaseUrl() + "/texter/" + idStr, "_blank", null);
			}
		}
	}
	
	private void viewDocument() {
		if (selectedRow > -1) {
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			String appPath = getAppPath();
			if(appPath != null && appPath.length() > 0 && !appPath.equals("ablage") ) {
				Window.open(getBaseUrl() + "/" + appPath + "/dok/" + idStr + "?draft=yes", "_blank", null);
			} else {
				Window.open(getBaseUrl() + "/dok/" + idStr + "?draft=yes", "_blank", null);
			}
		}
	}

	/* --------------------- Menu ----------------------- */

	private MenuBar getMenu() {
		MenuBar menuBar = new MenuBar(false);
		menuBar.addItem(createDocMenu());
		menuBar.addItem(createFolderMenu());
		menuBar.addItem(createEditMenu());
		return menuBar;
	}

	private MenuItem createDocMenu() {
		MenuBar submDoc = new MenuBar(true);
		MenuItem mntmCreateDocument = new MenuItem("Neu", false, new Command() {
			public void execute() {
				createDocument();
			}
		});
		submDoc.addItem(mntmCreateDocument);

		MenuItem mntmEditDocument = new MenuItem("Bearbeiten", false, new Command() {
			public void execute() {
				editDocument();
			}
		});
		submDoc.addItem(mntmEditDocument);

		MenuItem mntmDeleteDocument = new MenuItem("Loeschen", false, new Command() {
			public void execute() {
				deleteDocument();
			}
		});
		submDoc.addItem(mntmDeleteDocument);

		submDoc.addSeparator();

		MenuItem mntmViewDocument = new MenuItem("Ansehen / laden", false, new Command() {
			public void execute() {
				viewDocument();
			}
		});
		submDoc.addItem(mntmViewDocument);

		submDoc.addSeparator();

		MenuItem mntmFileDocument = new MenuItem("In Ordner ablegen...", false, new Command() {
			public void execute() {
				fileDocument();
			}
		});
		submDoc.addItem(mntmFileDocument);

		MenuItem mntmUnFileDocument = new MenuItem("Aus Ordner entfernen", false, new Command() {
			public void execute() {
				unfileDocument();
			}
		});
		submDoc.addItem(mntmUnFileDocument);

		submDoc.addSeparator();

		MenuItem mntmUpDocument = new MenuItem("Nach oben", false, new Command() {
			public void execute() {
				upDocument();
			}
		});
		submDoc.addItem(mntmUpDocument);

		MenuItem mntmDownDocument = new MenuItem("Nach unten", false, new Command() {
			public void execute() {
				downDocument();
			}
		});
		submDoc.addItem(mntmDownDocument);

		submDoc.addSeparator();

		MenuItem mntmUploadDocument = new MenuItem("Hochladen...", false, new Command() {
			public void execute() {
				uploadDocument();
			}
		});
		submDoc.addItem(mntmUploadDocument);

		MenuItem mntmUploadNewVersion = new MenuItem("Neue Version hochladen...", false, new Command() {
			public void execute() {
				uploadNewVersion();
			}
		});
		submDoc.addItem(mntmUploadNewVersion);

		submDoc.addSeparator();

		MenuItem mntmReindex = new MenuItem("Neu indizieren", false, new Command() {
			public void execute() {
				reindex();
			}
		});
		submDoc.addItem(mntmReindex);

		submDoc.addSeparator();

		MenuItem mntmShare = new MenuItem("Freigabe...", false, new Command() {
			public void execute() {
				shareDocument();
			}
		});
		submDoc.addItem(mntmShare);

		return new MenuItem("Dokument", false, submDoc);
	}
	
	private MenuItem createFolderMenu() {
		MenuBar submFolder = new MenuBar(true);
		MenuItem mntmCreateFolder = new MenuItem("Neu", false, new Command() {
			public void execute() {
				createFolder();
			}
		});
		submFolder.addItem(mntmCreateFolder);

		MenuItem mntmRenameFolder = new MenuItem("Umbenennen", false, new Command() {
			public void execute() {
				renameFolder();
			}
		});
		submFolder.addItem(mntmRenameFolder);

		submFolder.addSeparator();

		MenuItem mntmUpFolder = new MenuItem("Nach oben", false, new Command() {
			public void execute() {
				upFolder();
			}
		});
		submFolder.addItem(mntmUpFolder);

		MenuItem mntmDownFolder = new MenuItem("Nach unten", false, new Command() {
			public void execute() {
				downFolder();
			}
		});
		submFolder.addItem(mntmDownFolder);

		submFolder.addSeparator();

		MenuItem mntmMoveFolder = new MenuItem("Verschieben...", false, new Command() {
			public void execute() {
				moveFolder();//fileDocument();
			}
		});
		submFolder.addItem(mntmMoveFolder);

		return new MenuItem("Ordner", false, submFolder);
	}

	private MenuItem createEditMenu() {
		MenuBar submenu = new MenuBar(true);
		MenuItem mntmUnselectAll = new MenuItem("Auswahlen aufheben", false, new Command() {
			public void execute() {
				unselectAll();
			}
		});
		submenu.addItem(mntmUnselectAll);
		return new MenuItem("Bearbeiten", false, submenu);
	}

	/* ------------------- Menu logic ---------------------- */

	private void downDocument() {
		if (selectedRow > -1) {
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			TreeItem selectedTreeItem = tree.getSelectedItem();
			if (selectedTreeItem != null) {
				Object o = selectedTreeItem.getUserObject();
				if (o != null && o instanceof Folder) {
					Folder folder = (Folder) o;
					GWT.log("downDocument folder: " + folder.getId() + " doc: " + idStr);
					service.downDocument(folder.getId(), Integer.parseInt(idStr), new AsyncCallback<Integer>() {

						@Override
						public void onFailure(Throwable caught) {
							fehlermeldung(caught);
						}

						@Override
						public void onSuccess(Integer result) {
							updateDocumentList(new Integer(selectedRow + 1));
						}
					});
				} else {
					Window.alert("Bitte erst einen Ordner auswählen");
				}
			} else {
				Window.alert("Es ist kein Ordner ausgewählt.");
			}
		} else {
			Window.alert("Bitte erst ein Dokument auswählen.");
		}
	}

	private void upDocument() {
		if (selectedRow > -1) {
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			TreeItem selectedTreeItem = tree.getSelectedItem();
			if (selectedTreeItem != null) {
				Object o = selectedTreeItem.getUserObject();
				if (o != null && o instanceof Folder) {
					Folder folder = (Folder) o;
					//GWT.log("upDocument folder: " + folder.getId() + " doc: " + idStr);
					service.upDocument(folder.getId(), Integer.parseInt(idStr), new AsyncCallback<Integer>() {

						@Override
						public void onFailure(Throwable caught) {
							fehlermeldung(caught);
						}

						@Override
						public void onSuccess(Integer result) {
							updateDocumentList(new Integer(selectedRow - 1));
						}
					});
				} else {
					Window.alert("Das gewählte Baumelement ist kein Ordner.");
				}
			} else {
				Window.alert("Bitte erst einen Ordner auswählen");
			}
		} else {
			Window.alert("Bitte erst ein Dokument auswählen.");
		}
	}

	private void uploadDocument() {
		UploadDialog dlg = new UploadDialog();
		dlg.center();
		dlg.show();
	}

	private void uploadNewVersion() {
		if (selectedRow > -1) {
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			UploadDialog dlg = new UploadDialog(idStr);
			dlg.center();
			dlg.show();
		} else {
			Window.alert("Bitte erst ein Dokument auswählen.");
		}
	}
	
	private void reindex() {
		service.reindex(new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Ablage reindex error " + caught.getMessage());
			}

			@Override
			public void onSuccess(String result) {
				Window.alert(result);
			}});
	}

	@SuppressWarnings( { "rawtypes", "unchecked" })
	private void fileDocument() {
		if (selectedRow != UNSELECTED) {
			final String idStr = grid.getText(selectedRow, DOC_ID_COL);
			FolderSelector dlg = new FolderSelector(service);
			//dlg.setSize("300px", "400px");
			dlg.addCloseHandler(new CloseHandler() {
				public void onClose(CloseEvent event) {
					Object src = event.getSource();
					if (src instanceof FolderSelector) {
						FolderSelector dlg = (FolderSelector) src;
						if (dlg.getResult() == FolderSelector.RESULT_OK) {
							Folder selectedFolder = dlg.getSelectedFolder();
							service.addToFolder(selectedFolder, Integer.parseInt(idStr), new AsyncCallback() {
								@Override
								public void onFailure(Throwable caught) {
									fehlermeldung(caught);
								}

								@Override
								public void onSuccess(Object result) {
									// TODO evtl. irgendeine Rückmeldung an der
									// Bedienoberfläche, dass Aktion erfolgreich war
								}
							});
						}
					}
				}
			});

			dlg.setAnimationEnabled(true);
			dlg.center();
			dlg.show();
		} else {
			Window.alert("Select a document first");
		}
	}
	
	@SuppressWarnings( { "rawtypes", "unchecked" })
	private void deleteDocument() {
		if (selectedRow != UNSELECTED) {
			final String idStr = grid.getText(selectedRow, DOC_ID_COL);
			String docTitle = grid.getText(selectedRow, DOC_TITLE_COL);
			if(Window.confirm("Dokument " + idStr + " " + docTitle + " wirklich loeschen?")) {
				service.deleteDocument(Integer.parseInt(idStr), new AsyncCallback<Integer>(){
	
					@Override
					public void onFailure(Throwable caught) {
						fehlermeldung(caught);
					}
	
					@Override
					public void onSuccess(Integer result) {
						// etwas zur Bestaetigung des Loeschens tun
					}
				});
			}
		} else {
			Window.alert("Select a document first");
		}
	}
	
	@SuppressWarnings("unchecked")
	private void shareDocument() {
		if (selectedRow != UNSELECTED) {
			final String idStr = grid.getText(selectedRow, DOC_ID_COL);
			FreigabeDialog dlg = new FreigabeDialog(service, Integer.parseInt(idStr));

			dlg.addCloseHandler(new CloseHandler() {
				public void onClose(CloseEvent event) {
					// ..
				}
			});

			dlg.setAnimationEnabled(true);
			dlg.center();
			dlg.show();
		} else {
			Window.alert("Select a document first");
		}
	}

	@SuppressWarnings("unchecked")
	private void moveFolder() {
		final TreeItem selectedTreeItem = tree.getSelectedItem();
		if (selectedTreeItem != null) {
			Object o = selectedTreeItem.getUserObject();
			if (o != null && o instanceof Folder) {
				final Folder folder = (Folder) o;
				FolderSelector dlg = new FolderSelector(service);
				dlg.addCloseHandler(new CloseHandler() {
					public void onClose(CloseEvent event) {
						Object src = event.getSource();
						if (src instanceof FolderSelector) {
							FolderSelector dlg = (FolderSelector) src;
							if (dlg.getResult() == FolderSelector.RESULT_OK) {
								final Folder selectedFolder = dlg.getSelectedFolder();
								service.moveFolder(folder, selectedFolder.getId(), new AsyncCallback() {

									@Override
									public void onFailure(Throwable caught) {
										fehlermeldung(caught);
									}

									@Override
									public void onSuccess(Object result) {
										tree.removeItem(selectedTreeItem);
										tree.addFolder(null, selectedFolder, (Folder) result);
									}
									
								});
							}
						}
					}
				});

				dlg.setAnimationEnabled(true);
				dlg.center();
				dlg.show();
			}
		} else {
			Window.alert("Bitte erst einen Ordner auswaehlen");
		}
	}

	@SuppressWarnings( { "rawtypes", "unchecked" })
	private void unfileDocument() {
		if (selectedRow != UNSELECTED) {
			Folder folder = (Folder) tree.getSelectedItem().getUserObject();
			String idStr = grid.getText(selectedRow, DOC_ID_COL);
			service.removeFromFolder(folder, Integer.parseInt(idStr), new AsyncCallback() {
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("Webfiles.unfileDocument removeFromFolder error " + caught.getMessage());
				}

				@Override
				public void onSuccess(Object result) {
				}
			});
		} else {
			Window.alert("Bitte erst ein Dokument auswählen");
		}
	}

	private void unselectAll() {
		int rowCount = grid.getRowCount();
		for (int rowNo = 1; rowNo < rowCount; rowNo++) {
			grid.getRowFormatter().setStyleName(rowNo, "unselectedDocGridRow");
			selectedRow = UNSELECTED;
		}
	}
	
	private String getAppPath() {
		String appPath = null;
		String path = Window.Location.getPath();
		if(path != null && path.length() > 0) {
			appPath = path.substring(1);
			if(appPath != null && appPath.length() > 0) {
				int index = appPath.indexOf("/");
				if(index > -1) {
					appPath = appPath.substring(0, index);
				}
			}
		}
		return appPath;
	}

	private void createDocument() {
		//Window.alert("appPath=" + appPath); // liefert appPath=Netzpult
		String appPath = getAppPath();
		if(appPath != null && appPath.length() > 0 && !appPath.equals("ablage") ) {
			Window.open(getBaseUrl() + "/" + appPath + "/texter", "_blank", null);
		} else {
			Window.open(getBaseUrl() + "/texter", "_blank", null);
		}
	}

	private void createFolder() {
		Folder folder = new Folder();
		String folderName = Window.prompt("Name des Ordners?", "");
		if (folderName != null && folderName.length() > 0) {
			folder.setName(folderName);
			TreeItem selectedTreeItem = tree.getSelectedItem();
			if (selectedTreeItem == null) {
				folder.setParentId(Folder.ROOT_FOLDER_ID);
				createFolder(folder);
			} else {
				Folder selectedFolder = (Folder) selectedTreeItem.getUserObject();
				int selectedFolderId = selectedFolder.getId();
				if (selectedFolderId == Folder.NOT_FILED_FOLDER_ID || 
						selectedFolderId == Folder.DRAFT_FOLDER_ID) {
					Window.alert("Die Ordner 'Entwürfe' und 'nicht abgelegt' können keine Ordner enthalten");
				} else {
					folder.setParentId(((Folder) selectedTreeItem.getUserObject()).getId());
					createFolder(folder);
				}
			}
		}
	}

	private void createFolder(Folder folder) {
		service.createFolder(folder, new AsyncCallback<Folder>() {
			public void onFailure(Throwable caught) {
				Window.alert("Webfiles.createFolder createFolder error: " + caught.getMessage());
			}

			public void onSuccess(Folder result) {
				TreeItem item = new TreeItem();
				item.setText(result.getName());
				item.setUserObject(result);
				item.addItem("");
				TreeItem selectedTreeItem = tree.getSelectedItem();
				if (selectedTreeItem != null) {
					selectedTreeItem.addItem(item);
				} else {
					tree.addItem(item);
				}
				tree.setSelectedItem(item);
				selectedTreeItem = item;
			}
		});
	}

	private void upFolder() {
		final TreeItem selectedTreeItem = tree.getSelectedItem();
		if (selectedTreeItem != null) {
			Object o = selectedTreeItem.getUserObject();
			if (o != null && o instanceof Folder) {
				Folder folder = (Folder) o;
				service.upFolder(folder.getId(), new AsyncCallback<Integer>() {

					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Ablage.upFolder error: " + caught.getMessage());
					}

					@Override
					public void onSuccess(Integer result) {
						tree.upFolder();
					}
				});
			} else {
				Window.alert("Bitte erst einen Ordner ausw�hlen");
			}
		}
	}

	private void downFolder() {
		final TreeItem selectedTreeItem = tree.getSelectedItem();
		if (selectedTreeItem != null) {
			Object o = selectedTreeItem.getUserObject();
			if (o != null && o instanceof Folder) {
				Folder folder = (Folder) o;
				service.downFolder(folder.getId(), new AsyncCallback<Integer>() {

					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Ablage.downFolder error: " + caught.getMessage());
					}

					@Override
					public void onSuccess(Integer result) {
						tree.downFolder();
					}
				});
			}
		} else {
			Window.alert("Bitte erst einen Ordner ausw�hlen");
		}
	}

	@SuppressWarnings( { "unchecked", "rawtypes" })
	private void renameFolder() {
		final TreeItem selectedTreeItem = tree.getSelectedItem();
		if (selectedTreeItem != null) {
			Object o = selectedTreeItem.getUserObject();
			if (o != null && o instanceof Folder) {
				Folder folder = (Folder) o;
				final FolderRenameDialog dlg = new FolderRenameDialog(folder);
				dlg.addCloseHandler(new CloseHandler() {
					public void onClose(CloseEvent event) {
						if (dlg.getResult() == FolderRenameDialog.RESULT_OK) {
							final Folder renamedFolder = dlg.getFolder();
							service.updateFolder(renamedFolder, new AsyncCallback<Folder>() {
								public void onFailure(Throwable caught) {
									Window.alert("Webfiles.renameFolder error: " + caught.getMessage());
								}

								public void onSuccess(Folder result) {
									selectedTreeItem.setText(renamedFolder.getName());
									selectedTreeItem.setUserObject(renamedFolder);
								}
							});
						}
					}
				});
				dlg.center();
				dlg.setAnimationEnabled(true);
				dlg.show();
			}
		} else {
			Window.alert("Bitte erst einen Ordner auswaehlen");
		}
	}

	@Override
	public int getGestalt() {
		return Gestalt.ID_ABLAGE;
	}

	/*
	 * Hier sind alle Aufrufe an den Server als innere Klassen hinterlegt, die
	 * Unterst�tzung f�r Java EE konforme Authentifizierung erfordern. Sie sind
	 * als innere Klassen hinterlegt, weil sie konkrete Implementierungen f�r die
	 * Klasse Ablage sind und nicht wiederverwendbar sein m�ssen. Es handelt sich
	 * jeweils um Implementierungen der abstrakten Klasse ServerCall, die
	 * asynchrone Serveraufrufe in eine Form verpackt, die f�r GWT-RPC-Aufrufe
	 * eine Java EE konforme Authentifizierung erm�glicht.
	 */

	private class GetRootFoldersCall extends ServerCall {
		public GetRootFoldersCall(OwnerServiceAsync service, Command nextCall, Command exitCall) {
			super(service, nextCall, exitCall);
		}

		@SuppressWarnings("unchecked")
		@Override
		public void execute(Object result) {
			if (rpcService != null) {
				((OwnerServiceAsync) rpcService).getRootFolders(null, this);
			}
		}
	}

	private class GetUnfiledDocumentsCall extends ServerCall {
		public GetUnfiledDocumentsCall(Object service, Command nextCall, Command exitCall) {
			super(service, nextCall, exitCall);
		}

		@SuppressWarnings("unchecked")
		@Override
		public void execute(Object result) {
			if (rpcService != null) {
				((OwnerServiceAsync) rpcService).getUnfiledDocuments(this);
			}
		}
	}

	private class GetDraftDocumentsCall extends ServerCall {
		public GetDraftDocumentsCall(Object service, Command nextCall, Command exitCall) {
			super(service, nextCall, exitCall);
		}

		@SuppressWarnings("unchecked")
		@Override
		public void execute(Object result) {
			if (rpcService != null) {
				((OwnerServiceAsync) rpcService).getDraftDocuments(this);
			}
		}
	}

	private class GetSharedDocumentsCall extends ServerCall {
		public GetSharedDocumentsCall(Object service, Command nextCall, Command exitCall) {
			super(service, nextCall, exitCall);
		}

		@SuppressWarnings("unchecked")
		@Override
		public void execute(Object result) {
			if (rpcService != null) {
				((OwnerServiceAsync) rpcService).getSharedDocuments(this);
			}
		}
	}

	private class GetDocumentsCall extends ServerCall {
		private Folder folder;

		public GetDocumentsCall(Object service, Command nextCall, Command exitCall, Folder folder) {
			super(service, nextCall, exitCall);
			this.folder = folder;
		}

		@SuppressWarnings("unchecked")
		@Override
		public void execute(Object result) {
			if (rpcService != null) {
				((OwnerServiceAsync) rpcService).getDocuments(null, folder, this);
			}
		}
	}

	/*
	 * Der Code, der innerhalb der Klasse Ablage zur Verarbeitung asynchroner
	 * Serveraufrufe mit Unterst�tzung Java EE konformer Authentifizierung
	 * ausgef�hrt wird, ist hier als innere Klassen hinterlegt, um sie in Aufrufe
	 * der Klasse ServerCall verpacken zu k�nnen. Sie sind als innere Klassen
	 * angelegt, weil sie konkrete Implementierungen f�r die Klasse Ablage sind
	 * und nicht wiederverwendbar sein m�ssen
	 */

	private class AddFoldersCommand extends AbstractLinkedCommand {

		@SuppressWarnings("unchecked")
		@Override
		public void execute() {
			tree.addFolders((List<Folder>) result, null);
		}
	}

	private class PopulateGridCommand extends AbstractLinkedCommand {

		private Integer selRow;
		
		public PopulateGridCommand(Integer selRow) {
			this.selRow = selRow;
		}
		@SuppressWarnings("unchecked")
		@Override
		public void execute() {
			populateGrid(grid, (List<Document>) result, selRow);
		}
	}

	private class LoginExitCommand extends AbstractLinkedCommand {

		@Override
		public void execute() {
			Window.open(GWT.getHostPageBaseURL(), "_self", null);
		}

	}
}
